﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Quartz;
using System.Configuration;
using System.Data.Odbc;
using System.Collections;
using System.Data;
using System.Threading;
using System.IO;
using System.Diagnostics;
using log4net;
using QualityRpt.Service;
using QualityRpt.Utils;
using QualityRpt.Jobs;

namespace QualityRpt
{
    public class Job1 : IJob
    {
		private static readonly ILog logger = LogManager.GetLogger("Job1");
        public void Execute(IJobExecutionContext context)
        {
            lock (lockObj)
            {
                //优先执行任务
                JobRun();
                //执行原始数据导入任务
				RawDataJob.Run();
				//执行自动添加任务的策略
				AutoJob.Run();
            }
        }
		static Queue<int> EAJobQueue = new Queue<int>();//抽取任务、按日汇总及漏读分析任务（任务不能并行）
		static Queue<int> OtherJobQueue = new Queue<int>();//其他任务(任务可以并行)
		static Hashtable EAThreadHash = Hashtable.Synchronized(new Hashtable());//EA任务哈希表
		static Hashtable OtherThreadHash = Hashtable.Synchronized(new Hashtable());//其他任务哈希表
        static readonly object lockObj = new object();
		const string TABLE_TRANSNOTE = "RPT.TRANS_NOTE";
		const string TABLE_UNREAD = "RPT.UNREAD_TRANS_NOTE";
		const string TABLE_LB = "RPT.TRANS_LB";
		const string TABLE_TAMP = "RPT.TRANS_TAMP";
		const string TABLE_OBUCARD = "RPT.OBU_CARD_RELATION";
        /// <summary>
        /// Data_Status 
        /// 0 等待执行
        /// 1 正在执行
        /// 2 完成
        /// 3 失败
        /// 4 正在暂停
        /// 5 已暂停
		/// Job_type
		/// 0 抽取合并及所有分析任务的综合
		/// 10 合并抽取
		/// 11 按日汇总
		/// 12 漏读分析
		/// 13 邻道干扰分析
		/// 14 军车统计
        /// </summary>
        public void JobRun()
        {
            try
            {
                DateTime TimeNow = DateTime.Now;
                #region 任务暂停
                string sqlTWhere = "JOB_START_TIME<='" + TimeNow.ToString("yyyy-MM-dd HH:mm:ss") + "' AND DATA_STATUS=4"; ;
                DataTable queueTTable = ServiceInfoService.GetList(sqlTWhere, "ID ASC");
                string emptyFile = Environment.CurrentDirectory + "\\empty.txt";
                if (!File.Exists(emptyFile))
                {
                    File.WriteAllText(emptyFile, string.Empty);
                }
                for (int i = 0; i < queueTTable.Rows.Count;i++ )
                {
                    DataRow tRow = queueTTable.Rows[i];
                    int tjobID = Convert.ToInt32(tRow["ID"]);
                    if (EAThreadHash.ContainsKey(tjobID))
                    {
                        Thread tThread = EAThreadHash[tjobID] as Thread;
                        tThread.Abort();
                        //
						DBMJob.LoadQuery(TABLE_TRANSNOTE);DBMJob.LoadQuery(TABLE_LB);
						DBMJob.LoadQuery(TABLE_TAMP);DBMJob.LoadQuery(TABLE_UNREAD);
						DBMJob.LoadQuery(TABLE_OBUCARD);
                        EAThreadHash.Remove(tjobID);
                    }
                    else if (OtherThreadHash.ContainsKey(tjobID))
                    {
                        Thread tThread = OtherThreadHash[tjobID] as Thread;
                        tThread.Abort();
                        OtherThreadHash.Remove(tjobID);
                    }
                    tRow["DATA_STATUS"] = 5;
                    ServiceInfoService.Update(tRow);
                }
                #endregion
                #region 任务执行
                TimeNow = DateTime.Now;
                string sqlWhere = "JOB_START_TIME<='" + TimeNow.ToString("yyyy-MM-dd HH:mm:ss") + "' AND (DATA_STATUS=0 OR DATA_STATUS=3)";
                DataTable queueTable = ServiceInfoService.GetList(sqlWhere, "ID ASC");
                if (queueTable.Rows.Count > 0)
                {
                    logger.Info("读取到" + queueTable.Rows.Count + "个执行任务.");
                }
                for (int i = 0; i < queueTable.Rows.Count; i++)
                {
                    DataRow jobRow = queueTable.Rows[i];
                    int jobID = Convert.ToInt32(jobRow["ID"]);
                    int jobType = Convert.ToInt32(jobRow["JOB_TYPE"]);
                    if (jobType >= 0 && jobType <= 10)
                    {
                        if (!EAJobQueue.Contains(jobID))
                        {
                            EAJobQueue.Enqueue(jobID);
                            logger.Info("任务ID为" + jobID.ToString() + "的任务加入到任务队列");
                        }
                    }
                    else
                    {
                        if (!OtherJobQueue.Contains(jobID))
                        {
                            OtherJobQueue.Enqueue(jobID);
                            logger.Info("任务ID为" + jobID.ToString() + "的任务加入到任务队列");
                        }
                    }
                    
                }
                for (int i = 0; i < EAJobQueue.Count; i++)
                {
                    if (EAThreadHash.Count == 0)
                    {
                        int jobID = EAJobQueue.Dequeue();
                        DataRow jobRow = ServiceInfoService.Get(jobID);
                        Thread eaThread = new Thread(new ParameterizedThreadStart(RunEAJob));
                        EAThreadHash.Add(jobID, eaThread);
						jobRow["JOB_START_TIME"] = DateTime.Now;jobRow["DATA_STATUS"] = 1;//正在执行
                        ServiceInfoService.Update(jobRow);
                        eaThread.Start(jobRow);
                    }
                }
                for (int i = 0; i < OtherJobQueue.Count; i++)
                {
                    int jobID = OtherJobQueue.Dequeue();
                    if (!OtherThreadHash.ContainsKey(jobID))
                    {
                        DataRow jobRow = ServiceInfoService.Get(jobID);
                        Thread otherThread = new Thread(new ParameterizedThreadStart(RunStatJob));
                        OtherThreadHash.Add(jobID, otherThread);
						jobRow["JOB_START_TIME"] = DateTime.Now; jobRow["DATA_STATUS"] = 1;//正在执行
                        ServiceInfoService.Update(jobRow);
                        otherThread.Start(jobRow);
                    }
                }
                #endregion 
            }
            catch (System.Exception ex)
            {
                logger.Error("任务出错", ex);
            }
        }
        private void RunEAJob(object oRow)
        {
            DataRow jobRow = oRow as DataRow;
            int jobType = Convert.ToInt32(jobRow["JOB_TYPE"]);
            int jobID = Convert.ToInt32(jobRow["ID"]);
            logger.Info("队列中任务ID为" + jobID + "的任务接口开始执行");
			DateTime data_startTime = Convert.ToDateTime (jobRow ["DATA_START_TIME"]);
			DateTime data_endTime = Convert.ToDateTime (jobRow ["DATA_END_TIME"]);
            if (jobType == 0)//数据抽取等系统任务
            {
                try
                {
					jobRow["NOTE"] = DateTime.Now.ToString("yyyyMMdd HH:mm")+"合并抽取"+Environment.NewLine;//正在合并抽取数据
					ServiceInfoService.Update(jobRow);//
					TransNoteService.ExtractDataV2(data_startTime, data_endTime);
					DBMJob.RunStat (TABLE_TRANSNOTE);//运行一次概览收集
					jobRow["NOTE"] += DateTime.Now.ToString("HH:mm")+"按日汇总"+Environment.NewLine;//正在进行数据按日汇总
					ServiceInfoService.Update(jobRow);
					TransNoteService.StatData(data_startTime, data_endTime);
					jobRow["NOTE"] += DateTime.Now.ToString("HH:mm")+"漏读分析"+Environment.NewLine;//正在进行漏读分析
					ServiceInfoService.Update(jobRow);
					TransNoteService.AnalyUnreadData(data_startTime, data_endTime);
					DBMJob.RunStat(TABLE_UNREAD);
					JZTb(jobRow,data_startTime,data_endTime,jobID);//军车统计
					logger.Info("队列中任务ID为" + jobID + "的任务接口调用结束[合并抽取和汇总及分析]");
                    jobRow["JOB_END_TIME"] = DateTime.Now; jobRow["DATA_STATUS"] = 2;//任务完成
					jobRow["NOTE"] += DateTime.Now.ToString("HH:mm")+"任务完成";
                    ServiceInfoService.Update(jobRow);
                }
                catch (Exception ex)
                {
                    logger.Error(ex);
                    jobRow["JOB_END_TIME"] = DateTime.Now; jobRow["DATA_STATUS"] = 3;//任务失败,等待重新执行
                    ServiceInfoService.Update(jobRow);
                }
            }
            else if (jobType == 1)//合并抽取
            {
                try
                {
					jobRow["NOTE"] = DateTime.Now.ToString("yyyyMMdd HH:mm")+"开始合并抽取"+Environment.NewLine;//正在合并抽取数据
					ServiceInfoService.Update(jobRow);//
					TransNoteService.ExtractDataV2(data_startTime, data_endTime);
					DBMJob.RunStat(TABLE_TRANSNOTE);
                    logger.Info("队列中任务ID为" + jobID + "的任务接口调用结束[合并抽取]");
                    jobRow["JOB_END_TIME"] = DateTime.Now; jobRow["DATA_STATUS"] = 2;//任务完成
					jobRow["NOTE"] += DateTime.Now.ToString("HH:mm")+"任务完成";
                    ServiceInfoService.Update(jobRow);
                }
                catch (Exception ex)
                {
                    logger.Error(ex);
                    jobRow["JOB_END_TIME"] = DateTime.Now; jobRow["DATA_STATUS"] = 3;//任务失败,等待重新执行
                    ServiceInfoService.Update(jobRow);
                }
            }
            else if (jobType == 2)//按日汇总
            {
                try
                {
					jobRow["NOTE"] = DateTime.Now.ToString("yyyyMMdd HH:mm")+"开始数据按日汇总"+Environment.NewLine;//正在进行数据按日汇总
					ServiceInfoService.Update(jobRow);//
					TransNoteService.StatData(data_startTime,data_endTime);
                    logger.Info("队列中任务ID为" + jobID + "的任务接口调用结束[按日汇总]");
                    jobRow["JOB_END_TIME"] = DateTime.Now; jobRow["DATA_STATUS"] = 2;//任务完成
					jobRow["NOTE"] += DateTime.Now.ToString("HH:mm")+"任务完成";
                    ServiceInfoService.Update(jobRow);
                }
                catch (Exception ex)
                {
                    logger.Error(ex);
                    jobRow["JOB_END_TIME"] = DateTime.Now; jobRow["DATA_STATUS"] = 3;//任务失败,等待重新执行
                    ServiceInfoService.Update(jobRow);
                }
            }
            else if (jobType == 3)//漏读分析
            {
                try
                {
					jobRow["NOTE"] = DateTime.Now.ToString("yyyyMMdd HH:mm")+"漏读分析"+Environment.NewLine;//正在进行漏读分析
					ServiceInfoService.Update(jobRow);//
					TransNoteService.AnalyUnreadData(data_startTime, data_endTime);
                    logger.Info("队列中任务ID为" + jobID + "的任务接口调用结束[漏读分析].");
                    jobRow["JOB_END_TIME"] = DateTime.Now; jobRow["DATA_STATUS"] = 2;//任务完成
					jobRow["NOTE"] += DateTime.Now.ToString("HH:mm")+"任务完成";
                    ServiceInfoService.Update(jobRow);
                }
                catch (Exception ex)
                {
                    logger.Error(ex);
                    jobRow["JOB_END_TIME"] = DateTime.Now; jobRow["DATA_STATUS"] = 3;//任务失败,等待重新执行
                    ServiceInfoService.Update(jobRow);
                }
            }
			else if(jobType == 5){//军车统计
				try{
					JZTb(jobRow,data_startTime,data_endTime,jobID);
					logger.Info("队列中任务ID为" + jobID + "的任务接口调用结束[军车统计].");
					jobRow["JOB_END_TIME"] = DateTime.Now; jobRow["DATA_STATUS"] = 2;//任务完成
					jobRow["NOTE"] += DateTime.Now.ToString("HH:mm")+"任务完成";
					ServiceInfoService.Update(jobRow);
				}catch(Exception ex){
					logger.Error(ex);
					jobRow["JOB_END_TIME"] = DateTime.Now; jobRow["DATA_STATUS"] = 3;//任务失败,等待重新执行
					ServiceInfoService.Update(jobRow);
				}
			}
            EAThreadHash.Remove(jobID);//从表中删除
        }
		private void JZTb(DataRow jobRow,DateTime data_startTime,DateTime data_endTime,int jobID){
			jobRow["NOTE"] += DateTime.Now.ToString("yyyyMMdd HH:mm")+"军车统计"+Environment.NewLine;//正在进行军车统计
			ServiceInfoService.Update(jobRow);//
			DataTable jzTable = TransNoteService.GetJZTB(data_startTime, data_endTime);
			string strJzTemp = Thread.GetDomain().BaseDirectory +@"\军车统计模板.xls";
			string dirPath =Thread.GetDomain().BaseDirectory +@"\军车统计"; 
			if(!Directory.Exists(dirPath)){
				Directory.CreateDirectory(dirPath);
			}
			string jzFile = dirPath + @"\军车统计量"+data_startTime.ToString("yyyyMMdd")+"_"+data_endTime.ToString("yyyyMMdd")+".xls";
			logger.Info (jzFile);
			MemoryStream ms = ExcelUtils.RenderToExcelMs(jzTable,strJzTemp,null,1,true,0);
			ExcelUtils.RenderToFile(ms,jzFile);
			//发送EMAIL
			try{
			string toEmail = AppUtils.GetAppKey("toEmail");
			string email_title = "军车指标统计[ETC产品质量跟踪系统]";
			string email_content = "军车统计" + data_startTime.ToString ("yyyyMMdd") + "至" + data_endTime.ToString ("yyyyMMdd") + "时间段内军车通过情况";
			AppUtils.SendMail ("ETC产品质量跟踪系统", toEmail, email_title, email_content, jzFile, true);
			}catch(Exception ex){
				logger.Error (ex);
			}
		}
        /// <summary>
        /// 执行综合查询统计任务
        /// </summary>
        /// <param name="jobRow"></param>
        private void RunStatJob(object oRow)
        {
            DataRow jobRow = oRow as DataRow;
            int jobID = Convert.ToInt32(jobRow["ID"]);
            logger.Info("队列中任务ID为" + jobID + "的任务接口开始执行");
            try
            {
                int tempID = Convert.ToInt32(jobRow["TEMP_ID"]);
                DataRow tempRow = RPTResultService.GetTemplate(tempID);
                DataTable tempMetaTable = RPTResultService.GetTempMetaList(tempID);
                int jobDevID = Convert.ToInt32(tempRow["DEVICE_ID"]);
				int statTType = 0; bool statY2Y;bool statM2M;
                statTType = tempRow["STAT_TTYPE"] == DBNull.Value ? 0 : Convert.ToInt32(tempRow["STAT_TTYPE"]);
                int istatY2Y = tempRow["STAT_Y2Y"] == DBNull.Value ? 0 : Convert.ToInt32(tempRow["STAT_Y2Y"]);
                int istatM2M = tempRow["STAT_M2M"] == DBNull.Value ? 0 : Convert.ToInt32(tempRow["STAT_M2M"]);
                int istatUnread = tempRow["STAT_UNREAD"] == DBNull.Value ? 0 : Convert.ToInt32(tempRow["STAT_UNREAD"]);
                statY2Y = istatY2Y > 0 ? true : false; statM2M = istatM2M > 0 ? true : false;
                DateTime startTime = Convert.ToDateTime(jobRow["DATA_START_TIME"]); DateTime endTime = Convert.ToDateTime(jobRow["DATA_END_TIME"]);
                List<string> numstartList = new List<string>();
                List<string> numendList = new List<string>();
                Hashtable hashgroup = new Hashtable();
                string spin = string.Empty; string specin = string.Empty; string cnin = string.Empty;
                string rdin = string.Empty; string plazain = string.Empty; string lanein = string.Empty;
                for (int k = 0; k < tempMetaTable.Rows.Count; k++)
                {
                    DataRow metaRow = tempMetaTable.Rows[k];
                    object metaGroup = metaRow["META_GROUP"];
                    if (metaGroup != null && metaGroup != DBNull.Value && !hashgroup.ContainsKey(metaGroup))
                    {
                        DataRow[] numSelRows = tempMetaTable.Select("META_GROUP = '" + metaGroup.ToString() + "'");
                        for (int mm = 0; mm < numSelRows.Length; mm++)
                        {
                            if (numSelRows[mm]["META_SYMBOL"].ToString() == ">=")
                            {
                                numstartList.Add(StringUtils.XmlToContent(metaRow["META_VALUE"].ToString()));
                            }
                            else
                            {
                                numendList.Add(StringUtils.XmlToContent(metaRow["META_VALUE"].ToString()));
                            }
                        }
                        hashgroup.Add(metaGroup, 0);
                    }
                    else
                    {
                        if (metaRow["META_KEY"].ToString() == "SUPPLIER_ID")
                        {
                            spin = StringUtils.XmlToContent(metaRow["META_VALUE"].ToString());
                        }
                        else if (metaRow["META_KEY"].ToString() == "SPEC_ID")
                        {
                            specin = StringUtils.XmlToContent(metaRow["META_VALUE"].ToString());
                        }
                        else if (metaRow["META_KEY"].ToString() == "CONTRACT_NO")
                        {
                            cnin = StringUtils.XmlToContent(metaRow["META_VALUE"].ToString());
                        }
                        else if (metaRow["META_KEY"].ToString() == "ROAD_ID")
                        {
                            rdin = StringUtils.XmlToContent(metaRow["META_VALUE"].ToString());
                        }
                        else if (metaRow["META_KEY"].ToString() == "PLAZA_ID")
                        {
                            plazain = StringUtils.XmlToContent(metaRow["META_VALUE"].ToString());
                        }
                        else if (metaRow["META_KEY"].ToString() == "LANE_NO")
                        {
                            lanein = StringUtils.XmlToContent(metaRow["META_VALUE"].ToString());
                        }
                    }

                }
                DataTable statTable = null;
                if (jobDevID == DeviceService.OBU_DEV)//电子标签智能查询系统
                {
                    bool fromTempTable = false; bool statUnread = false;
                    int ifromTemp = tempRow["FROM_TEMP"] == DBNull.Value ? 0 : Convert.ToInt32(tempRow["FROM_TEMP"]);
                    fromTempTable = ifromTemp > 0 ? true : false; statUnread = istatUnread > 0 ? true : false;
                    //StringBuilder sbCallTxt = new StringBuilder();
                    //sbCallTxt.Append(startTime.ToString()+"|"+endTime.ToString()+"|"+spin.ToString()+"|"+specin.ToString()+"|"+cnin.ToString()+"|"+rdin.ToString()+"|"+plazain.ToString()+"|"+lanein.ToString());
                    //logger.Info(sbCallTxt.ToString());
                    statTable = TransNoteService.GetOBUStatByQ(startTime, endTime, string.Empty, statTType, spin, specin, cnin, rdin, plazain, lanein, statUnread, fromTempTable, numstartList.ToArray(), numendList.ToArray());
                }
                else if (jobDevID == DeviceService.AIRWIRE_DEV)
                {
                    bool statUnread = false;
                    statUnread = istatUnread > 0 ? true : false;
                    statTable = TransNoteService.GetAIRStatByQ(startTime, endTime, string.Empty, statTType, spin, specin, rdin, plazain, lanein, statUnread);
                }
                else if (jobDevID == DeviceService.ICARD_DEV)
                {
                    bool fromTempTable = false;
                    int ifromTemp = tempRow["FROM_TEMP"] == DBNull.Value ? 0 : Convert.ToInt32(tempRow["FROM_TEMP"]);
                    fromTempTable = ifromTemp > 0 ? true : false;
                    statTable = TransNoteService.GetCARDStatByQ(startTime, endTime, string.Empty, statTType, spin, specin, cnin, rdin, plazain, lanein, fromTempTable, numstartList.ToArray(), numendList.ToArray());
                }
                DataTable result_table = RPTResultService.GetSchema();
                for (int kk = 0; kk < statTable.Rows.Count; kk++)
                {
                    DataRow sRow = statTable.Rows[kk];
                    DataRow rsRow = result_table.NewRow();
                    for (int j = 0; j < statTable.Columns.Count; j++)
                    {
                        string columnName = statTable.Columns[j].ColumnName;
                        if (result_table.Columns.Contains(columnName))
                        {
                            rsRow[columnName] = sRow[columnName];
                        }
                    }
                    result_table.Rows.Add(rsRow);
                }
                RPTResultService.Save(Convert.ToInt32(jobRow["ID"]), result_table);
                jobRow["JOB_END_TIME"] = DateTime.Now; jobRow["DATA_STATUS"] = 2;//任务完成
                ServiceInfoService.Update(jobRow);
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                jobRow["JOB_END_TIME"] = DateTime.Now; jobRow["DATA_STATUS"] = 3;//任务失败
                ServiceInfoService.Update(jobRow);
            }
            OtherThreadHash.Remove(jobID);
        }

    }
}
